﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using UnityEngine.UI;

namespace Nirvana
{
	/// <summary>
	/// 过场CG动画控制脚本
	/// </summary>
	public sealed class CGController : MonoBehaviour
	{
		private PlayableDirector director;
		private Action endCallback;
		private List<GameObject> newActorList = new List<GameObject>();
		private bool isPlaying = false;

		[SerializeField]
		[Tooltip("The Skip Btn")]
		[AssetType(typeof(Button))]
		private Button skinBtn = null;

		[SerializeField]
		[Tooltip("需要挂在主角身上的特效")]
		private AttachTransform[] roleEffects;

		// 在unity编辑器下改动track的mute会保存在本地导致svn经常有变化。在cg结束时恢复到旧值
		private Dictionary<string, bool> oldTrackMuteDic = new Dictionary<string, bool>();
		private void Awake()
		{
			this.director = this.GetComponentInChildren<PlayableDirector>();

			if (null != this.skinBtn)
			{
				this.skinBtn.onClick.AddListener(this.Skip);
			}
		}

		void Update()
        {
			if(this.isPlaying && PlayState.Playing != this.director.state)
            {
				this.isPlaying = false;
				this.OnPlayEnd();
            }
			if (this.isPlaying && PlayState.Playing == this.director.state)
			{
				this.isPlaying = true;
			}

		}

		/// <summary>
		/// 添加CG动画主角
		/// </summary>
		/// <param name="actor"></param>
		/// <param name="trackname"></param>
		public bool AddActor(GameObject newActor,string trackname)
        {
			if (newActor == null) return false;
			var asset = this.director.playableAsset;
			if (asset == null) return false;

			bool isSucc = false;
			if (newActor.GetComponent<Animator>() == null) newActor.AddComponent<Animator>();
			foreach(var p in asset.outputs)
            {
				if(p.streamName == trackname)
                {
					var track = p.sourceObject as AnimationTrack;
					var oldActor = this.director.GetGenericBinding(track) as GameObject;
					if(oldActor != null)
                    {
						// cg里添加的脚本组件
						var oldAttach = oldActor.GetComponent<AttachTransform>();
						if(oldAttach != null && newActor.GetComponent<AttachTransform>() == null)
                        {
							AttachTransform new_attach = newActor.AddComponent<AttachTransform>();
							new_attach.target = oldAttach.target;
							new_attach.offset = oldAttach.offset;
						}
						oldActor.SetActive(false);
						newActor.SetActive(true);
					}
					this.director.SetGenericBinding(track, newActor);
					this.ChangeAttachTranform(newActor.transform);
					isSucc = true;
					break;

				}
            }

			if (isSucc)
			{
				this.newActorList.Add(newActor);
			}

			return isSucc;
		}

		//设置覆盖名称的轨道是否激活。
		public void SetTrackMute(string track_name, bool is_mute)
		{
			List<TrackAsset> track_list = new List<TrackAsset>();
			this.GetTrackAssetList(track_name, track_list);

			foreach (var track in track_list)
			{
#if UNITY_EDITOR
				if (!this.oldTrackMuteDic.ContainsKey(track.name))
				{
					this.oldTrackMuteDic.Add(track.name, track.muted);
				}
#endif
				track.muted = is_mute;
			}
		}

		private void GetTrackAssetList(string track_name, List<TrackAsset> track_list)
		{
			if (null == this.director || null == track_list)
			{
				return;
			}

			PlayableAsset playable_asset = this.director.playableAsset;
			if (null == playable_asset)
			{
				return;
			}

			foreach (PlayableBinding pb in playable_asset.outputs)
			{
				RecursionGetTrackAsset(pb.sourceObject as TrackAsset, track_name, track_list);
			}
		}
		private void RecursionGetTrackAsset(TrackAsset track_asset, string track_name, List<TrackAsset> track_list)
		{
			if (null == track_asset)
			{
				return;
			}

			if (track_asset.name == track_name)
			{
				track_list.Add(track_asset);
			}

			IEnumerable<TrackAsset> track_asset_list = track_asset.GetChildTracks();
			foreach (TrackAsset child_track in track_asset_list)
			{
				this.RecursionGetTrackAsset(child_track, track_name, track_list);
			}
		}

		public void SetPlayEndCallback(Action end_callback = null)
		{
			this.endCallback = end_callback;
		}

		//播放CG
		public void Play()
		{
			if (null == this.director)
			{
				return;
			}

			this.director.Play();
		}

		//停止CG
		public void Stop()
		{
			if (null == this.director)
			{
				return;
			}

			this.director.Stop();
			this.Clear();
			this.endCallback = null;
		}

		//跳过CG
		public void Skip()
		{
			if (null == this.director || PlayState.Playing != this.director.state)
			{
				return;
			}

			this.director.Stop();
			this.OnPlayEnd();
		}

		//播放完成
		private void OnPlayEnd()
		{
			this.Clear();
			//结束回调
			if (null != this.endCallback)
			{
				this.endCallback();
				this.endCallback = null;
			}
		}


		//关闭CG控制器
		private void Clear()
		{
			foreach (GameObject actor in this.newActorList)
			{
				if (null == actor)
				{
					continue;
				}

				actor.SetActive(true);
				AttachTransform attach_transform = actor.GetComponent<AttachTransform>();
				if (null != attach_transform)
				{
					Destroy(attach_transform);
				}
			}

			this.newActorList.Clear();

#if UNITY_EDITOR
			foreach (KeyValuePair<string, bool> track_mute in this.oldTrackMuteDic)
			{
				List<TrackAsset> track_list = new List<TrackAsset>();
				this.GetTrackAssetList(track_mute.Key, track_list);
				foreach (var track_asset in track_list)
				{
					track_asset.muted = track_mute.Value;
				}
			}

			this.oldTrackMuteDic.Clear();
#endif
		}

		//更改添加的效果对象附件到对应的节点上
		private void ChangeAttachTranform(Transform actor)
		{
			foreach (var attach in this.roleEffects)
			{
				if (null != attach && null != attach.target)
				{
					var newTrans = actor.Find(attach.target.name);
					if (null != newTrans)
					{
						attach.target = newTrans;
					}
				}
			}
		}

	}
}

